package com.lobov.entities.yale;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.text.DecimalFormat;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;

import com.lobov.entities.EntityIface;
import com.lobov.entities.Timer;
import com.lobov.utils.Generator;

/**
 * Матрица в йельском формате - структура данных для хранения математической
 * матрицы чисел двойной точности
 * 
 */
public class MatrixYale extends Timer implements EntityIface, Serializable {

	private static final long serialVersionUID = 1L;

	public MatrixYale(SparseVector[] vectors, boolean compressed) {
		super();
		this.vectors = vectors;
		this.compressed = compressed;
	}

	public MatrixYale(int xLength, int yLength) {
		this.vectors = new SparseVector[yLength];
		for (int i = 0; i < yLength; i++) {
			vectors[i] = Generator.generateEmptyVector(xLength, i);
		}
		this.compressed = false;
	}

	private SparseVector[] vectors;
	private boolean compressed;
	private boolean flipped = false;

	public SparseVector[] getVectors() {
		return vectors;
	}

	public void setVectors(SparseVector[] vectors) {
		this.vectors = vectors;
	}

	public void setCompressed(boolean compressed) {
		this.compressed = compressed;
	}

	@Override
	public double getElementByXY(int x, int y) throws Exception {
		return vectors[y - 1].getElementByX(x - 1);
	}

	/**
	 * не используется в данном типе, всегда возвращает 0!!!
	 */
	@Override
	public double getElementByX(int x) throws Exception {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public boolean isCompressed() {
		return compressed;
	}

	@Override
	public EntityIface compress() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public EntityIface deCompress() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	public void addVector(SparseVector vector, int position) throws Exception {
		if (position > vectors.length - 1) {
			throw new Exception(
					"Вы пытаетесь вставить вектор за пределы матричного пространства, - позиция превышает "
							+ (vectors.length - 1));
		}
		vectors[position] = vector;
	}

	public boolean isFlipped() {
		return flipped;
	}

	public void setFlipped(boolean flipped) {
		this.flipped = flipped;
	}

	public int getXlength() {
		return vectors[1].getxLength();
	}

	public int getYlength() {
		return vectors.length;
	}

	/**
	 * unused!!!
	 */
	@Override
	public void setElementByX(int x, double value) throws Exception {
		// TODO Auto-generated method stub
	}

	@Override
	public void setElementByXY(int x, int y, double value) throws Exception {
		vectors[y - 1].setElementByX((x - 1), value);
	}

	public SparseVector getVector(int position) {
		return vectors[position];
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (int y = 0; y < getYlength(); y++) {
			for (int x = 0; x < getXlength(); x++) {
				try {
					DecimalFormat df = new DecimalFormat("#.##");
					sb.append(df.format(vectors[y].getElementByX(x)));
				} catch (Exception e) {
					e.printStackTrace();
				}
				sb.append(" ");
			}
			sb.append("\n");
		}
		return sb.toString();
	}

	/**
	 * 
	 * @return строка, содержащая матрицу в текстовом формате (для передачи в
	 *         форматк UTF TXT в MapReduce) 
	 *         !entity! - маркер начала блока сущности (M - матрица, 1...n - лоскут) 
	 *         #vector# - маркер границ блока векторал
	 *         $value$  - маркер границ блока значений (разделитель ' $$ ')
	 *         %position% - маркер границ блока координат значений (разделитель ' %% ')
	 */
	public String toStringData() {
		StringBuilder sb = new StringBuilder("M!");
		for (int i = 0; i < vectors.length; i++) {

			sb.append("#vector#");

			double[] values = vectors[i].getValues();
			int xs[] = vectors[i].getXs();

			for (int p = 0; p < values.length; p++) {
				//TODO
			}
			for (int x = 0; x < xs.length; x++) {
				//TODO
			}
		}
		return sb.toString();
	}
	
	public Text toText() {
		Text text = null;
		StringBuilder sb = new StringBuilder();
		for (int y = 0; y < getYlength(); y++) {
			for (int x = 0; x < getXlength(); x++) {
				try {
					sb.append(vectors[y].getElementByX(x));
				} catch (Exception e) {
					e.printStackTrace();
				}
				sb.append(" ");
			}
			sb.append("#");
		}
		
		text = new Text(sb.toString());
		return text;
	}
	
	
}
